package com.hc.kotlin

import java.io.File
import com.hc.randomGet as rG //导入其他扩展函数并取别名

fun main8() {
    var fs1:OClass<Food> = FoodStore()
    var fs2:OClass<Food> = FastFoodStore() //协变
    var fs3:OClass<Food> = BurgerStore() //协变
//    var fs4:OClass<FastFoodStore> = FoodStore()
    var fc1:IClass<Food> = FoodConsumer()
//    var fc2:IClass<Food> = FastFoodConsumer()
    var fc3:IClass<FastFood> = FoodConsumer() //逆变
    var fc4:IClass<Burger> = FoodConsumer() //逆变
    var ff1:CClass<Food> = FatherFood() //不变
//    var ff2:CClass<Food> = SonFood()
    var ff3:CClass<FastFood> = SonFood() //不变
//    var ff4:CClass<FastFood> = FatherFood()
//    reified+inline 防泛型擦除
}
fun main9() {
    println("Hello".addExt(2))
    "123".pl().addExt(2).pl()
    println("HelLo".yuanyincount)
    "Hello World" easyPrint "!"
    var list = mutableListOf(1,2,3,4,5)
    println(list.rG())
}
fun main() {
//    public inline fun <T> T.apply(block: T.() -> Unit): T {
//        block()
//        return this
//    }
//    T.() -> Unit 匿名扩展函数
    fun File.noname():Unit {
        this.setReadable(true)
    }
    var block = File::noname
    var file = File("xxx")
    file.apply(block)
}

infix fun String.easyPrint(a:String){ //单个参数的扩展函数使用infix可以省略.和()
    println(this+" ${a}")
}
val String.yuanyincount //扩展属性
    get() = count { "aeiou".contains(it) }
fun String.addExt(a:Int):String{ //扩展函数
    return this+"!".repeat(a)
}

fun <T> T.pl():T{ //泛型扩展函数  apply also let run
    println(this)
    return this
}
interface OClass<out T>{ //协变:使用泛型时,父类引用指向子类对象
    fun f1():T
}
interface IClass<in T>{ //逆变:使用泛型时,子类引用指向父类对象
    fun f1(t:T)
}
interface CClass<T>{ //不变:即java泛型规则,不能存在继承关系
    fun f1():T
    fun f2(t:T)
}
open class Food{}
open class FastFood:Food()
class Burger:FastFood()

class FoodStore:OClass<Food>{
    override fun f1(): Food {
        return Food()
    }
}
class FastFoodStore:OClass<FastFood>{
    override fun f1(): FastFood {
        return FastFood()
    }
}
class BurgerStore:OClass<Burger>{
    override fun f1(): Burger {
        return Burger()
    }
}
class FoodConsumer:IClass<Food>{
    override fun f1(t: Food) {
        TODO("Not yet implemented")
    }
}
class FastFoodConsumer:IClass<FastFood>{
    override fun f1(t: FastFood) {
        TODO("Not yet implemented")
    }
}
class BurgerConsumer:IClass<Burger>{
    override fun f1(t: Burger) {
        TODO("Not yet implemented")
    }
}
class FatherFood:CClass<Food>{
    override fun f1(): Food {
        return Food()
    }

    override fun f2(t: Food) {
        TODO("Not yet implemented")
    }
}
class SonFood:CClass<FastFood>{
    override fun f1(): FastFood {
        return FastFood()
    }
    override fun f2(t: FastFood) {
        TODO("Not yet implemented")
    }
}